/**
 * Bun SQLite 性能测试
 */

import { Database } from 'bun:sqlite';

// 测试配置
const config = {
  insertCount: 10000,        // 插入记录数
  queryCount: 1000,          // 查询次数
  updateCount: 1000,         // 更新次数
  deleteCount: 1000,         // 删除次数
  transactionSize: 100,      // 每个事务的操作数
  useTransactions: true,     // 是否使用事务
  useMemoryDb: true,         // 是否使用内存数据库
  dbPath: './benchmark.db',  // 文件数据库路径
};

// 计时器
class Timer {
  private startTime: number = 0;
  private endTime: number = 0;

  start(): void {
    this.startTime = performance.now();
  }

  stop(): void {
    this.endTime = performance.now();
  }

  get elapsedMs(): number {
    return this.endTime - this.startTime;
  }

  get elapsedSeconds(): number {
    return this.elapsedMs / 1000;
  }

  get operationsPerSecond(): number {
    return 0;
  }
}

// 插入测试计时器
class InsertTimer extends Timer {
  constructor(private count: number) {
    super();
  }

  get operationsPerSecond(): number {
    return this.count / this.elapsedSeconds;
  }
}

// 查询测试计时器
class QueryTimer extends Timer {
  constructor(private count: number) {
    super();
  }

  get operationsPerSecond(): number {
    return this.count / this.elapsedSeconds;
  }
}

// 更新测试计时器
class UpdateTimer extends Timer {
  constructor(private count: number) {
    super();
  }

  get operationsPerSecond(): number {
    return this.count / this.elapsedSeconds;
  }
}

// 删除测试计时器
class DeleteTimer extends Timer {
  constructor(private count: number) {
    super();
  }

  get operationsPerSecond(): number {
    return this.count / this.elapsedSeconds;
  }
}

// 事务测试计时器
class TransactionTimer extends Timer {
  constructor(private count: number, private batchSize: number) {
    super();
  }

  get operationsPerSecond(): number {
    return (this.count * this.batchSize) / this.elapsedSeconds;
  }

  get transactionsPerSecond(): number {
    return this.count / this.elapsedSeconds;
  }
}

async function runBenchmark() {
  console.log('Bun SQLite 性能测试');
  console.log('配置:', config);
  
  // 创建数据库
  const dbPath = config.useMemoryDb ? ':memory:' : config.dbPath;
  console.log(`使用数据库: ${config.useMemoryDb ? '内存数据库' : dbPath}`);
  
  const db = new Database(dbPath);
  
  try {
    // 创建表
    db.exec(`
      CREATE TABLE IF NOT EXISTS benchmark (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        value TEXT NOT NULL,
        number INTEGER NOT NULL,
        timestamp INTEGER NOT NULL
      )
    `);
    
    // 准备语句
    const insertStmt = db.prepare('INSERT INTO benchmark (value, number, timestamp) VALUES (?, ?, ?)');
    const queryStmt = db.prepare('SELECT * FROM benchmark WHERE id = ?');
    const updateStmt = db.prepare('UPDATE benchmark SET value = ?, number = ? WHERE id = ?');
    const deleteStmt = db.prepare('DELETE FROM benchmark WHERE id = ?');
    
    // 插入测试
    console.log(`\n执行 ${config.insertCount} 次插入操作...`);
    const insertTimer = new InsertTimer(config.insertCount);
    insertTimer.start();
    
    if (config.useTransactions) {
      const batchSize = config.transactionSize;
      const batchCount = Math.ceil(config.insertCount / batchSize);
      
      for (let b = 0; b < batchCount; b++) {
        db.exec('BEGIN TRANSACTION');
        
        const start = b * batchSize;
        const end = Math.min(start + batchSize, config.insertCount);
        
        for (let i = start; i < end; i++) {
          const value = `value-${i}`;
          const number = i;
          const timestamp = Date.now();
          
          insertStmt.run(value, number, timestamp);
        }
        
        db.exec('COMMIT');
      }
    } else {
      for (let i = 0; i < config.insertCount; i++) {
        const value = `value-${i}`;
        const number = i;
        const timestamp = Date.now();
        
        insertStmt.run(value, number, timestamp);
      }
    }
    
    insertTimer.stop();
    console.log(`插入完成: ${insertTimer.elapsedMs.toFixed(2)} ms`);
    console.log(`每秒插入: ${insertTimer.operationsPerSecond.toFixed(2)} ops/sec`);
    
    // 查询测试
    console.log(`\n执行 ${config.queryCount} 次查询操作...`);
    const queryTimer = new QueryTimer(config.queryCount);
    queryTimer.start();
    
    for (let i = 0; i < config.queryCount; i++) {
      const id = Math.floor(Math.random() * config.insertCount) + 1;
      queryStmt.get(id);
    }
    
    queryTimer.stop();
    console.log(`查询完成: ${queryTimer.elapsedMs.toFixed(2)} ms`);
    console.log(`每秒查询: ${queryTimer.operationsPerSecond.toFixed(2)} ops/sec`);
    
    // 更新测试
    console.log(`\n执行 ${config.updateCount} 次更新操作...`);
    const updateTimer = new UpdateTimer(config.updateCount);
    updateTimer.start();
    
    if (config.useTransactions) {
      const batchSize = config.transactionSize;
      const batchCount = Math.ceil(config.updateCount / batchSize);
      
      for (let b = 0; b < batchCount; b++) {
        db.exec('BEGIN TRANSACTION');
        
        const start = b * batchSize;
        const end = Math.min(start + batchSize, config.updateCount);
        
        for (let i = start; i < end; i++) {
          const id = Math.floor(Math.random() * config.insertCount) + 1;
          const value = `updated-${i}`;
          const number = i * 10;
          
          updateStmt.run(value, number, id);
        }
        
        db.exec('COMMIT');
      }
    } else {
      for (let i = 0; i < config.updateCount; i++) {
        const id = Math.floor(Math.random() * config.insertCount) + 1;
        const value = `updated-${i}`;
        const number = i * 10;
        
        updateStmt.run(value, number, id);
      }
    }
    
    updateTimer.stop();
    console.log(`更新完成: ${updateTimer.elapsedMs.toFixed(2)} ms`);
    console.log(`每秒更新: ${updateTimer.operationsPerSecond.toFixed(2)} ops/sec`);
    
    // 删除测试
    console.log(`\n执行 ${config.deleteCount} 次删除操作...`);
    const deleteTimer = new DeleteTimer(config.deleteCount);
    deleteTimer.start();
    
    if (config.useTransactions) {
      const batchSize = config.transactionSize;
      const batchCount = Math.ceil(config.deleteCount / batchSize);
      
      for (let b = 0; b < batchCount; b++) {
        db.exec('BEGIN TRANSACTION');
        
        const start = b * batchSize;
        const end = Math.min(start + batchSize, config.deleteCount);
        
        for (let i = start; i < end; i++) {
          const id = Math.floor(Math.random() * config.insertCount) + 1;
          deleteStmt.run(id);
        }
        
        db.exec('COMMIT');
      }
    } else {
      for (let i = 0; i < config.deleteCount; i++) {
        const id = Math.floor(Math.random() * config.insertCount) + 1;
        deleteStmt.run(id);
      }
    }
    
    deleteTimer.stop();
    console.log(`删除完成: ${deleteTimer.elapsedMs.toFixed(2)} ms`);
    console.log(`每秒删除: ${deleteTimer.operationsPerSecond.toFixed(2)} ops/sec`);
    
    // 事务性能测试
    console.log('\n事务性能测试...');
    const transactionCount = 100;
    const operationsPerTransaction = 100;
    const transactionTimer = new TransactionTimer(transactionCount, operationsPerTransaction);
    
    transactionTimer.start();
    
    for (let t = 0; t < transactionCount; t++) {
      db.exec('BEGIN TRANSACTION');
      
      for (let i = 0; i < operationsPerTransaction; i++) {
        const value = `transaction-${t}-${i}`;
        const number = t * 1000 + i;
        const timestamp = Date.now();
        
        insertStmt.run(value, number, timestamp);
      }
      
      db.exec('COMMIT');
    }
    
    transactionTimer.stop();
    console.log(`事务测试完成: ${transactionTimer.elapsedMs.toFixed(2)} ms`);
    console.log(`每秒事务: ${transactionTimer.transactionsPerSecond.toFixed(2)} txn/sec`);
    console.log(`每秒操作: ${transactionTimer.operationsPerSecond.toFixed(2)} ops/sec`);
    
    // 总结
    console.log('\n性能测试总结:');
    console.log('操作类型\t\t每秒操作数\t\t耗时(ms)');
    console.log('-'.repeat(60));
    console.log(`插入\t\t${insertTimer.operationsPerSecond.toFixed(2)}\t\t${insertTimer.elapsedMs.toFixed(2)}`);
    console.log(`查询\t\t${queryTimer.operationsPerSecond.toFixed(2)}\t\t${queryTimer.elapsedMs.toFixed(2)}`);
    console.log(`更新\t\t${updateTimer.operationsPerSecond.toFixed(2)}\t\t${updateTimer.elapsedMs.toFixed(2)}`);
    console.log(`删除\t\t${deleteTimer.operationsPerSecond.toFixed(2)}\t\t${deleteTimer.elapsedMs.toFixed(2)}`);
    console.log(`事务\t\t${transactionTimer.operationsPerSecond.toFixed(2)}\t\t${transactionTimer.elapsedMs.toFixed(2)}`);
    
  } catch (error) {
    console.error('运行 Bun SQLite 性能测试时出错:', error);
  } finally {
    // 关闭数据库连接
    db.close();
    
    // 如果不是内存数据库，尝试删除测试数据库文件
    if (!config.useMemoryDb) {
      try {
        Bun.file(config.dbPath).remove();
        console.log(`已删除测试数据库文件: ${config.dbPath}`);
      } catch (error) {
        console.error(`删除测试数据库文件失败: ${error}`);
      }
    }
  }
}

// 运行基准测试
runBenchmark().catch(console.error); 